using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.I18N
{
	internal class UTF16ConvUTF8 : Conv
	{
		private delegate int ConvertToCharsDelegate<T>(byte[] bytes, int byteOffsets, int byteCounts, T[] chars, int charOffset, ref int charCount, ref int remainingBytes, bool bUseReplacementChar);

		public override int MinBytesPerChar => 1;

		public override int MaxBytesPerChar => 3;

		internal UTF16ConvUTF8(int oracleId)
			: base(oracleId)
		{
		}

		private static int GetCharsLengthImpl(byte[] bytes, int byteOffset, int byteCount, ref int bytesCounted)
		{
			int num = 0;
			int num2 = byteOffset;
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			bool flag = true;
			while (num2 < num3 && flag)
			{
				switch ((bytes[num2] & 0xF0) / 16)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					num2++;
					num++;
					break;
				case 12:
				case 13:
					if (num2 + 1 >= num3)
					{
						flag = false;
						break;
					}
					num++;
					num2 += 2;
					break;
				case 14:
				{
					if (num2 + 2 >= num3)
					{
						flag = false;
						break;
					}
					ushort c = (ushort)(((bytes[num2] & 0xF) << 12) | ((bytes[num2 + 1] & 0x3F) << 6) | (bytes[num2 + 2] & 0x3F));
					num2 += 3;
					num++;
					if (UTF16ConvUtility.IsHiSurrogate((char)c))
					{
						if (num2 + 2 >= num3)
						{
							flag = false;
							break;
						}
						num2 += 3;
						num++;
					}
					break;
				}
				default:
					num2++;
					num++;
					break;
				}
			}
			bytesCounted = num2 - byteOffset;
			return num;
		}

		private int GetBytesOffsetImpl(byte[] bytes, int byteOffset, int byteCount, ref int charCount)
		{
			int num = 0;
			int num2 = byteOffset;
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			bool flag = true;
			while (num2 < num3 && flag && num < charCount)
			{
				switch ((bytes[num2] & 0xF0) / 16)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					num2++;
					num++;
					break;
				case 12:
				case 13:
					if (num2 + 1 >= num3)
					{
						flag = false;
						break;
					}
					num++;
					num2 += 2;
					break;
				case 14:
				{
					if (num2 + 2 >= num3)
					{
						flag = false;
						break;
					}
					ushort c = (ushort)(((bytes[num2] & 0xF) << 12) | ((bytes[num2 + 1] & 0x3F) << 6) | (bytes[num2 + 2] & 0x3F));
					num2 += 3;
					num++;
					if (UTF16ConvUtility.IsHiSurrogate((char)c))
					{
						if (num2 + 2 >= num3)
						{
							flag = false;
							break;
						}
						num2 += 3;
						num++;
					}
					break;
				}
				default:
					num2++;
					num++;
					break;
				}
			}
			charCount = num;
			return num2 - byteOffset;
		}

		public override int GetBytesOffset(byte[] bytes, int byteOffset, int byteCount, int charCount)
		{
			int charCount2 = charCount;
			return GetBytesOffsetImpl(bytes, byteOffset, byteCount, ref charCount2);
		}

		private static int UTFToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, ref int remainingBytes, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = charOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + charCount;
			if (num4 > chars.Length)
			{
				num4 = chars.Length;
			}
			bool flag = true;
			while (num < num2 && num3 < num4 && flag)
			{
				byte b = bytes[num++];
				switch ((b & 0xF0) / 16)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					chars[num3++] = (char)b;
					break;
				case 12:
				case 13:
				{
					if (num >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char c2 = ((b >= 194 && b <= 223 && (bytes[num] & 0xC0) == 128) ? ((char)((uint)((b & 0x1F) << 6) | (bytes[num] & 0x3Fu))) : '\ufffd');
					num++;
					chars[num3++] = c2;
					if (ccb || c2 != '\ufffd')
					{
						break;
					}
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				case 14:
				{
					if (num + 1 >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						remainingBytes = 3;
						flag = false;
						num--;
						break;
					}
					char c = (((b == 224 && (bytes[num] & 0xE0) == 160 && (bytes[num + 1] & 0xC0) == 128) || (b >= 225 && b <= 239 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128)) ? ((char)((uint)(((b & 0xF) << 12) | ((bytes[num] & 0x3F) << 6)) | (bytes[num + 1] & 0x3Fu))) : '\ufffd');
					num += 2;
					if ((b != Conv.REP_CHAR_UTF8[0] || bytes[num - 2] != Conv.REP_CHAR_UTF8[1] || bytes[num - 1] != Conv.REP_CHAR_UTF8[2]) && !ccb && c == '\ufffd')
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					if (UTF16ConvUtility.IsHiSurrogate(c))
					{
						if (num >= num2)
						{
							remainingBytes = 6;
							flag = false;
							num -= 3;
							break;
						}
						b = bytes[num];
						if ((byte)(b & 0xF0) != 224)
						{
							chars[num3++] = '\ufffd';
							if (ccb)
							{
								break;
							}
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						if (num + 2 >= num2)
						{
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
							}
							remainingBytes = 6;
							flag = false;
							num -= 3;
							break;
						}
						if (num3 + 1 >= num4)
						{
							flag = false;
							num -= 3;
							break;
						}
						num++;
						char c2 = (((b == 224 && (bytes[num] & 0xE0) == 160 && (bytes[num + 1] & 0xC0) == 128) || (b >= 225 && b <= 239 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128)) ? ((char)((uint)(((b & 0xF) << 12) | ((bytes[num] & 0x3F) << 6)) | (bytes[num + 1] & 0x3Fu))) : '\ufffd');
						num += 2;
						if (UTF16ConvUtility.IsLoSurrogate(c2))
						{
							chars[num3++] = c;
						}
						else
						{
							chars[num3++] = '\ufffd';
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
							}
						}
						chars[num3++] = c2;
					}
					else
					{
						chars[num3++] = c;
					}
					break;
				}
				default:
					chars[num3++] = '\ufffd';
					if (!ccb)
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					break;
				}
			}
			charCount = num3 - charOffset;
			return num - offset;
		}

		private static int UTFToUTF16Bytes(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, ref int remainingBytes, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = utfOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + utfCount;
			if (num4 > utfbytes.Length)
			{
				num4 = utfbytes.Length;
			}
			bool flag = true;
			while (num < num2 && num3 + 1 < num4 && flag)
			{
				byte b = bytes[num++];
				switch ((b & 0xF0) / 16)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					utfbytes[num3++] = b;
					utfbytes[num3++] = 0;
					break;
				case 12:
				case 13:
				{
					if (num >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char c = ((b >= 194 && b <= 223 && (bytes[num] & 0xC0) == 128) ? ((char)((uint)((b & 0x1F) << 6) | (bytes[num] & 0x3Fu))) : '\ufffd');
					num++;
					utfbytes[num3++] = (byte)(c & 0xFFu);
					utfbytes[num3++] = (byte)((int)c >> 8);
					if (ccb || c != '\ufffd')
					{
						break;
					}
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				case 14:
				{
					if (num + 1 >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						remainingBytes = 3;
						flag = false;
						num--;
						break;
					}
					char c2 = (((b == 224 && (bytes[num] & 0xE0) == 160 && (bytes[num + 1] & 0xC0) == 128) || (b >= 225 && b <= 239 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128)) ? ((char)((uint)(((b & 0xF) << 12) | ((bytes[num] & 0x3F) << 6)) | (bytes[num + 1] & 0x3Fu))) : '\ufffd');
					num += 2;
					if ((b != Conv.REP_CHAR_UTF8[0] || bytes[num - 2] != Conv.REP_CHAR_UTF8[1] || bytes[num - 1] != Conv.REP_CHAR_UTF8[2]) && !ccb && c2 == '\ufffd')
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					if (UTF16ConvUtility.IsHiSurrogate(c2))
					{
						if (num >= num2)
						{
							remainingBytes = 6;
							flag = false;
							num -= 3;
							break;
						}
						b = bytes[num];
						if ((byte)(b & 0xF0) != 224)
						{
							utfbytes[num3++] = 253;
							utfbytes[num3++] = byte.MaxValue;
							if (ccb)
							{
								break;
							}
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						if (num + 2 >= num2)
						{
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
							}
							remainingBytes = 6;
							flag = false;
							num -= 3;
							break;
						}
						if (num3 + 3 >= num4)
						{
							num -= 3;
							break;
						}
						num++;
						char c = (((b == 224 && (bytes[num] & 0xE0) == 160 && (bytes[num + 1] & 0xC0) == 128) || (b >= 225 && b <= 239 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128)) ? ((char)((uint)(((b & 0xF) << 12) | ((bytes[num] & 0x3F) << 6)) | (bytes[num + 1] & 0x3Fu))) : '\ufffd');
						num += 2;
						if (UTF16ConvUtility.IsLoSurrogate(c))
						{
							utfbytes[num3++] = (byte)(c2 & 0xFFu);
							utfbytes[num3++] = (byte)((int)c2 >> 8);
						}
						else
						{
							utfbytes[num3++] = 253;
							utfbytes[num3++] = byte.MaxValue;
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
							}
						}
						utfbytes[num3++] = (byte)(c & 0xFFu);
						utfbytes[num3++] = (byte)((int)c >> 8);
					}
					else
					{
						utfbytes[num3++] = (byte)(c2 & 0xFFu);
						utfbytes[num3++] = (byte)((int)c2 >> 8);
					}
					break;
				}
				default:
					if (num3 + 1 < num4)
					{
						utfbytes[num3++] = 253;
						utfbytes[num3++] = byte.MaxValue;
					}
					if (!ccb)
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					break;
				}
			}
			utfCount = num3 - utfOffset;
			return num - offset;
		}

		public override int GetBytesLength(char[] chars, int charOffset, int charCount)
		{
			int num = charOffset;
			int num2 = charOffset + charCount;
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			for (int i = num; i < num2; i++)
			{
				int num4 = chars[i];
				num3 = ((num4 >= 0 && num4 <= 127) ? (num3 + 1) : ((num4 <= 2047) ? (num3 + 2) : (num3 + 3)));
			}
			return num3;
		}

		public override int GetBytesLength(string chars, int charOffset, int charCount)
		{
			int num = charOffset;
			int num2 = charOffset + charCount;
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			for (int i = num; i < num2; i++)
			{
				int num4 = chars[i];
				num3 = ((num4 >= 0 && num4 <= 127) ? (num3 + 1) : ((num4 <= 2047) ? (num3 + 2) : (num3 + 3)));
			}
			return num3;
		}

		public override int GetBytesLength(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount)
		{
			int num = utf16BytesOffset;
			int num2 = utf16BytesOffset + utf16BytesCount;
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			for (int i = num; i < num2 - 1; i += 2)
			{
				int num4 = (utf16Bytes[i + 1] << 8) | utf16Bytes[i];
				num3 = ((num4 >= 0 && num4 <= 127) ? (num3 + 1) : ((num4 <= 2047) ? (num3 + 2) : (num3 + 3)));
			}
			return num3;
		}

		public override int ConvertCharsToBytes(char[] chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool bUseReplacementChar)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2; i++)
			{
				if (num4 >= num3)
				{
					break;
				}
				int num5 = chars[i];
				if (num5 >= 0 && num5 <= 127)
				{
					bytes[num4++] = (byte)num5;
				}
				else if (num5 > 2047)
				{
					if (num4 + 2 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xE0u | ((uint)(num5 >> 12) & 0xFu));
					bytes[num4++] = (byte)(0x80u | ((uint)(num5 >> 6) & 0x3Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
				else
				{
					if (num4 + 1 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xC0u | ((uint)(num5 >> 6) & 0x1Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertStringToBytes(string chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool bUseReplacementChar)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2; i++)
			{
				if (num4 >= num3)
				{
					break;
				}
				int num5 = chars[i];
				if (num5 >= 0 && num5 <= 127)
				{
					bytes[num4++] = (byte)num5;
				}
				else if (num5 > 2047)
				{
					if (num4 + 2 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xE0u | ((uint)(num5 >> 12) & 0xFu));
					bytes[num4++] = (byte)(0x80u | ((uint)(num5 >> 6) & 0x3Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
				else
				{
					if (num4 + 1 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xC0u | ((uint)(num5 >> 6) & 0x1Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertUTF16ToBytes(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount, byte[] bytes, int byteOffset, ref int byteCount, bool bUseReplacementChar = true)
		{
			int num = utf16BytesOffset;
			int num2 = num + utf16BytesCount;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			if (byteOffset < 0)
			{
				byteOffset = 0;
			}
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = byteOffset;
			int i;
			for (i = num; i < num2 - 1; i += 2)
			{
				if (num4 >= num3)
				{
					break;
				}
				int num5 = (utf16Bytes[i + 1] << 8) | utf16Bytes[i];
				if (num5 >= 0 && num5 <= 127)
				{
					bytes[num4++] = (byte)num5;
				}
				else if (num5 > 2047)
				{
					if (num4 + 2 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xE0u | ((uint)(num5 >> 12) & 0xFu));
					bytes[num4++] = (byte)(0x80u | ((uint)(num5 >> 6) & 0x3Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
				else
				{
					if (num4 + 1 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xC0u | ((uint)(num5 >> 6) & 0x1Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
			}
			byteCount = num4 - byteOffset;
			return i - num;
		}

		public override int ConvertBytesToChars(byte[] bytes, int byteOffset, int byteCount, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			int remainingBytes = 0;
			return UTFToChars(bytes, byteOffset, byteCount, chars, charOffset, ref charCount, ref remainingBytes, bUseReplacementChar);
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int byteOffset, int byteCount, byte[] utf16Bytes, int utf16BytesOffset, ref int utf16BytesCount, bool bUseReplacementChar)
		{
			int remainingBytes = 0;
			return UTFToUTF16Bytes(bytes, byteOffset, byteCount, utf16Bytes, utf16BytesOffset, ref utf16BytesCount, ref remainingBytes, bUseReplacementChar);
		}

		private int ConvertUtf8ArraySegListToCharsImpl<T>(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, T[] chars, int charOffset, ref int charCount, bool bUseReplacementChar, ConvertToCharsDelegate<T> t)
		{
			int num = charOffset;
			int charCount2 = charCount;
			int num2 = 0;
			int num3 = 0;
			int remainingBytes = 0;
			int continuationOffset = 0;
			byte[] array = null;
			int byteCounts = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (bytesOffset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, bytesOffset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				if (charCount2 <= 0)
				{
					break;
				}
				int num4 = bytes[i].Offset + continuationOffset;
				int num5 = bytes[i].Count - continuationOffset;
				if (i == idx)
				{
					num4 = offSet + continuationOffset;
					num5 = bytes[i].Count - (offSet - bytes[i].Offset) - continuationOffset;
				}
				if (bytesCount - num3 <= num5)
				{
					num5 = bytesCount - num3;
					flag = true;
				}
				int num6 = t(bytes[i].Array, num4, num5, chars, num, ref charCount2, ref remainingBytes, bUseReplacementChar);
				num3 += num6;
				num += charCount2;
				num2 += charCount2;
				charCount2 = charCount - num2;
				if (charCount2 > 0 && num6 < num5 && !flag && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[6];
					}
					byte[] array2 = bytes[i + 1].Array;
					int num7 = num4 + num6;
					byte b = bytes[i].Array[num7];
					int num8 = (b & 0xF0) / 16;
					int buffer1Bytes = num5 - num6;
					switch (num8)
					{
					case 12:
					case 13:
						array[0] = b;
						array[1] = array2[bytes[i + 1].Offset];
						continuationOffset = 1;
						byteCounts = 2;
						break;
					case 14:
						UTF16ConvUtility.GetRemainingBytes(remainingBytes, bytes[i].Array, num7, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						byteCounts = remainingBytes;
						if (remainingBytes == 3 && UTF16ConvUtility.IsHiSurrogate(UTF16ConvUtility.Conv3ByteUTFtoUTF16(array[0], array[1], array[2])))
						{
							UTF16ConvUtility.GetRemainingBytes(6, bytes[i].Array, num7, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
							remainingBytes = 6;
							byteCounts = 6;
						}
						break;
					}
					num6 = t(array, 0, byteCounts, chars, num, ref charCount2, ref remainingBytes, bUseReplacementChar);
					if (num6 == 0)
					{
						break;
					}
					num3 += num6;
					num += charCount2;
					num2 += charCount2;
					charCount2 = charCount - num2;
				}
				else
				{
					continuationOffset = 0;
				}
			}
			charCount = num2;
			return num3;
		}

		public override int GetBytesOffset(IList<ArraySegment<byte>> bytes, int charCount)
		{
			int charCount2 = charCount;
			int num = 0;
			int num2 = 0;
			int continuationOffset = 0;
			byte[] array = null;
			int byteCount = 0;
			for (int i = 0; i < bytes.Count; i++)
			{
				if (num >= charCount)
				{
					break;
				}
				byte[] array2 = bytes[i].Array;
				int num3 = bytes[i].Offset + continuationOffset;
				int num4 = bytes[i].Count - continuationOffset;
				int bytesOffsetImpl = GetBytesOffsetImpl(array2, num3, num4, ref charCount2);
				num2 += bytesOffsetImpl;
				num += charCount2;
				charCount2 = charCount - num;
				if (charCount2 > 0 && bytesOffsetImpl < num4 && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[6];
					}
					byte[] array3 = bytes[i + 1].Array;
					int num5 = num3 + bytesOffsetImpl;
					byte b = array2[num5];
					int num6 = (b & 0xF0) / 16;
					int buffer1Bytes = num4 - bytesOffsetImpl;
					switch (num6)
					{
					case 12:
					case 13:
						array[0] = b;
						array[1] = array3[bytes[i + 1].Offset];
						continuationOffset = 1;
						byteCount = 2;
						break;
					case 14:
						UTF16ConvUtility.GetRemainingBytes(3, array2, num5, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						byteCount = 3;
						if (UTF16ConvUtility.IsHiSurrogate(UTF16ConvUtility.Conv3ByteUTFtoUTF16(array[0], array[1], array[2])))
						{
							UTF16ConvUtility.GetRemainingBytes(6, array2, num5, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
							byteCount = 6;
						}
						break;
					}
					bytesOffsetImpl = GetBytesOffsetImpl(array, 0, byteCount, ref charCount2);
					num2 += bytesOffsetImpl;
					num += charCount2;
					charCount2 = charCount - num;
				}
				else
				{
					continuationOffset = 0;
				}
			}
			return num2;
		}

		public override int ConvertBytesToChars(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			if (bytes.Count == 1)
			{
				return ConvertBytesToChars(bytes[0].Array, bytes[0].Offset + bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar);
			}
			return ConvertUtf8ArraySegListToCharsImpl(bytes, bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar, UTFToChars);
		}

		public override int GetCharsLength(byte[] bytes, int byteOffset, int byteCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthImpl(bytes, byteOffset, byteCount, ref bytesCounted);
		}

		public override int GetCharsLength(ArraySegment<byte> bytes, int bytesOffset, int bytesCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthImpl(bytes.Array, bytes.Offset + bytesOffset, bytesCount, ref bytesCounted);
		}

		public override int GetCharsLength(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount)
		{
			return UTF16ConvUtility.GetCharsLengthListSegs(bytes, bytesOffset, bytesCount, GetCharsLengthImpl);
		}
	}
}
